<template>
  <div class="init-container">
    <div class="mask-container" v-if="isMask"></div>
    <div class="rectifier-container">
      <div class="top-panel">
        <!-- 设定参数区 -->
        <div class="config-section">
          <Tabs type="card" name="config-section">
            <TabPane
              v-for="item of settingConfigs"
              :key="item.tankID"
              :label="item.label"
              :name="item.name"
              tab="config-section"
            >
              <RectifierConfigPanel
                :config="item"
                @onSaveForm="handleFromValueChange"
                @onSaveTable="handleTableValueChange"
              />
            </TabPane>
          </Tabs>
        </div>

        <!-- 运行参数区 -->
        <div class="runtime-section">
          <RuntimeParams :data="tankData" @param-change="handleParamUpdate" />
        </div>
      </div>

      <!-- 曲线图区 -->
      <div class="chart-section">
        <div
          v-for="(chart, key) in chartData"
          :key="key"
          :class="`${key}-chart`"
        >
          <div class="left">
            <div class="time-range-picker">
              <TimePicker
                type="timerange"
                format="HH:mm"
                confirm
                v-model="dateTime[key]"
                @on-ok="handleTimeRangeChange(key, 'HH:mm')"
                @on-clear="handleTimeRangeChange(key, 'HH:mm')"
                placeholder="选择时间范围"
              ></TimePicker>
            </div>
            <div class="device-selector">
              <CheckboxGroup v-model="selectedSlots[key]" :max="3">
                <Checkbox label="sulfuric11">
                  <span class="label-text">硫酸11槽</span>
                </Checkbox>
                <Checkbox label="sulfuric12">
                  <span class="label-text">硫酸12槽</span>
                </Checkbox>
                <Checkbox label="chromic15">
                  <span class="label-text">铬酸15槽</span>
                </Checkbox>
              </CheckboxGroup>
            </div>
          </div>
          <BaseChart
            :title="`${key === 'voltage' ? '电压' : '电流'}曲线`"
            :colorPalette="colorPalette"
            :data="chart"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import BaseChart from './components/BaseChart.vue';
import RectifierConfigPanel from './components/RectifierConfigPanel.vue';
import RuntimeParams from './components/RuntimeParams.vue';
import {
  N_RectifierSettings,
  T_srv,
  Tsrv,
  chromic15Config,
  sulfuric11Config,
  sulfuric12Config,
  tanksData,
  vue,
  ifs,
  chartData,
  I_cmd,
  T_cmd
} from './config';

@T_srv.comp({
  components: {
    RectifierConfigPanel,
    RuntimeParams,
    BaseChart
  }
})
export default class cRectifierSettings extends vue {
  private name = 'cRectifierSettings';

  private G_compName: string = this.name;

  /* 组件箱信息对象 */
  private GT_compBoxInfo: ifs.I_compBoxInfo;

  /* 组件箱对象 */
  private GT_compBox: ifs.I_compBox;

  private compBoxInfo: ifs.I_compBoxInfo;

  /* 组件箱识别ID */
  private G_compID: string;

  /* 指挥部 */
  private GT_command: I_cmd = new T_cmd();

  public isMask: boolean = false;

  private settingConfigs: N_RectifierSettings.slotConfig[] = [
    sulfuric11Config(),
    sulfuric12Config(),
    chromic15Config()
  ];

  private chartData = chartData();

  private colorPalette: string[] = ['#ff0000', '#00ff00', '#0000ff'];

  private tankData: N_RectifierSettings.TankData[] = tanksData();

  private selectedSlots: Record<string, string[]> = {
    voltage: ['sulfuric11', 'sulfuric12', 'chromic15'],
    current: ['sulfuric11', 'sulfuric12', 'chromic15']
  };

  private dateTime = {
    voltage: [null, null],
    current: [null, null]
  };

  public ecDetCodes: string[] = [];

  @T_srv.watch('selectedSlots', { deep: true })
  onDeviceChange(
    newVal: Record<string, string[]>,
    oldVal: Record<string, string[]>
  ) {
    const newVoltage = Tsrv.utils.md5(JSON.stringify(newVal.voltage));
    const newCurrent = Tsrv.utils.md5(JSON.stringify(newVal.current));
    const oldVoltage = Tsrv.utils.md5(JSON.stringify(oldVal.voltage));
    const oldCurrent = Tsrv.utils.md5(JSON.stringify(oldVal.current));

    // if (newVoltage !== oldVoltage) {
    //   this.handleDeviceChange('voltage', newVal.voltage);
    // } else if (newCurrent !== oldCurrent) {
    //   this.handleDeviceChange('current', newVal.current);
    // }
    this.handleDeviceChange('voltage', newVal.voltage);
    this.handleDeviceChange('current', newVal.current);
  }

  created() {
    this.GT_compBoxInfo = Tsrv.getCompInfo(this.compBoxInfo);
    this.G_compID = this.GT_compBoxInfo.compID;
    this.GT_compBox = this.GT_compBoxInfo.TcompBox;
    this.GT_command.init(this, this.GT_compBoxInfo);

    this.dateTime.current = this.getDefaultRange();
    this.dateTime.voltage = this.getDefaultRange();
    this.initData();
  }

  mounted() {
    this.GT_compBox.addCompMergeName(this.G_compID, this.G_compName, this);
    this.$emit('compBoxInfo', this.GT_compBoxInfo);

    this.GT_command.startTask();
    this.handleTimeRangeChange('voltage', 'YYYY-MM-DD HH:mm:ss');
    this.handleTimeRangeChange('current', 'YYYY-MM-DD HH:mm:ss');
    this.receiveEvent();
  }

  private receiveEvent() {
    this.$bus.$on(
      '__PLC_CONNSTATE__',
      (data: { connState: boolean; ecBoxName: string }) => {
        if (data.ecBoxName === 'mianyang') {
          if (data.connState) {
            if (!this.GT_command.isOpenTask) {
              this.GT_command.startTask();
            }
          } else {
            this.GT_command.stopTask();
          }
        }
      }
    );
  }

  destroyed() {
    this.GT_command.stopTask();
    this.GT_compBox.removeCompMergeName(this.G_compID, this.G_compName);
    this.$bus.$off('__PLC_CONNSTATE__');

    if (Tsrv.utils.isEmpty(this.compBoxInfo)) {
      this.GT_compBox.removeCompsWithCompID(this.G_compID);
    } else {
      this.GT_compBox.removeCompsMergeName(this.G_compID, [
        `'${this.G_compName}'`
      ]);
    }
  }

  private initData() {
    const codes = [];
    this.settingConfigs.forEach(config => {
      config.configData.forEach(row => {
        codes.push(row.code);
      });
      config.stages.forEach(stage => {
        Object.values(stage).forEach(row => {
          if (row.code !== undefined) {
            codes.push(row.code);
          }
        });
      });
      codes.push(config.modeInfo.code);
    });

    this.tankData.forEach(tank => {
      Object.values(tank).forEach(row => {
        if (row.code !== undefined) {
          codes.push(row.code);
        }
      });
    });

    this.ecDetCodes = codes;
  }

  public updateData(res: ifs.I_scadaReadResp['data']) {
    this.settingConfigs.forEach(config => {
      config.configData.forEach(row => {
        if (row.code !== undefined) {
          if (row.conversionRate !== undefined) {
            row.value = res[row.code].v / row.conversionRate;
          } else {
            row.value = res[row.code].v;
          }
        }
      });

      config.stages.forEach(stage => {
        Object.values(stage).forEach(row => {
          if (row.code !== undefined) {
            if (row.conversionRate !== undefined) {
              row.value = res[row.code].v / row.conversionRate;
            } else {
              row.value = res[row.code].v;
            }
          }
        });
      });

      config.modeInfo.value = res[config.modeInfo.code].v;
    });

    this.tankData.forEach(tank => {
      Object.values(tank).forEach(row => {
        if (row.code !== undefined) {
          if (row.conversionRate !== undefined) {
            row.value = res[row.code].v / row.conversionRate;
          } else {
            row.value = res[row.code].v;
          }
        }
      });
    });
  }

  private getDefaultRange(): [Date, Date] {
    const end = new Date();
    const start = new Date(end.getTime() - 600000);
    return [start, end];
  }

  private handleFromValueChange(obj: {
    tanID: number;
    row: N_RectifierSettings.ConfigItem;
  }) {
    const { code, value } = obj.row;
    const data = [
      {
        ecDetCode: code,
        value:
          obj.row.conversionRate === undefined
            ? value.toString()
            : (Number(value) * obj.row.conversionRate).toString()
      }
    ];
    Tsrv.writePlcData(data).then(_ => {
      Tsrv.readPlcData([code]).then(res => {
        if (typeof res !== 'boolean') {
          this.settingConfigs.forEach(config => {
            if (obj.tanID === config.tankID) {
              config.configData.forEach(row => {
                if (row.code === code) {
                  if (row.conversionRate === undefined) {
                    row.value = res[code].v;
                  } else {
                    row.value = res[code].v / row.conversionRate;
                  }
                }
              });
            }
          });
        }
      });
    });
  }

  private handleTableValueChange(obj: {
    tankID: number;
    paramName: string;
    index: number;
    val: number;
  }) {
    const { tankID, paramName, index, val } = obj;
    const row = this.settingConfigs.find(config => config.tankID === tankID)
      ?.stages[index][paramName];

    const data = [
      {
        ecDetCode: row.code,
        value:
          row.conversionRate === undefined
            ? val.toString()
            : (val * row.conversionRate).toString()
      }
    ];
    Tsrv.writePlcData(data).then(_ => {
      Tsrv.readPlcData([row.code]).then(res => {
        if (typeof res !== 'boolean') {
          if (row.conversionRate === undefined) {
            row.value = res[row.code].v;
          } else {
            row.value = res[row.code].v / row.conversionRate;
          }
        }
      });
    });
  }

  private handleParamUpdate(obj: {
    tank: string;
    field: string;
    value: number;
  }) {
    const { tank, field, value } = obj;
    const row: N_RectifierSettings.setInfo = this.tankData.find(
      t => t.name === tank
    )?.[field];

    const data = [
      {
        ecDetCode: row.code,
        value:
          row.conversionRate === undefined
            ? value.toString()
            : (value * row.conversionRate).toString()
      }
    ];
    Tsrv.writePlcData(data).then(_ => {
      Tsrv.readPlcData([row.code]).then(res => {
        if (typeof res !== 'boolean') {
          this.tankData.forEach(t => {
            if (t.name === tank) {
              if (row.conversionRate === undefined) {
                t[field].value = res[row.code].v;
              } else {
                t[field].value = res[row.code].v / row.conversionRate;
              }
            }
          });
        }
      });
    });
  }

  private async handleTimeRangeChange(
    chartType: 'voltage' | 'current',
    dateType: string
  ) {
    try {
      if (!chartType || !this.dateTime[chartType]) return;

      let [start, end] = ['', ''];
      if (dateType === 'YYYY-MM-DD HH:mm:ss') {
        start = new Date(
          this.formatDateTime(this.dateTime[chartType][0])
        ).toISOString();
        end = new Date(
          this.formatDateTime(this.dateTime[chartType][1])
        ).toISOString();
      } else {
        start = new Date(
          this.formatDateTime(this.dateTime[chartType][0], 'time')
        ).toISOString();
        end = new Date(
          this.formatDateTime(this.dateTime[chartType][1], 'time')
        ).toISOString();
      }

      const codes = this.selectedSlots[chartType]
        .map(
          slot =>
            this.chartData[chartType].find(item => item.key === slot)?.code
        )
        .filter(Boolean);

      const params: ifs.I_qryDataReq = {
        ecCodes: codes,
        beginTime: start,
        endTime: end,
        pageNo: 1,
        pageSize: 999
      };

      const res = await Tsrv.getQueryData(params);
      if (typeof res === 'boolean' || Tsrv.noValue(res)) return;

      // 使用降采样处理数据
      this.chartData[chartType] = this.chartData[chartType].map(item => {
        if (!res[item.code] || res[item.code].d.length === 0) return item;

        // 对原始数据进行降采样处理，采样间隔1分钟（60000毫秒）
        const sampledData = this.downsampleData(res[item.code].d, 60000);

        return {
          ...item,
          values: sampledData.map(d => [
            new Date(d.t).getTime(),
            d.v / item.conversionRate
          ])
        };
      });
    } catch (error) {
      console.error('获取数据失败:', error);
    }
  }

  private formatDateTime(
    input: string | Date,
    dateType: 'time' | 'iso' = 'iso'
  ) {
    let date: Date;

    if (dateType === 'time') {
      const [hours, minutes] = (input as string).split(':').map(Number);
      date = new Date();
      date.setHours(hours, minutes, 0, 0);
    } else {
      date = new Date(input);
    }

    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    const hours = String(date.getHours()).padStart(2, '0');
    const minutes = String(date.getMinutes()).padStart(2, '0');
    const seconds = String(date.getSeconds()).padStart(2, '0');

    return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  }

  // 新增降采样方法
  private downsampleData(data: ifs.I_codeData['d'], interval: number) {
    if (!data || data.length === 0) return [];

    // 按时间排序
    const sortedData = data.sort(
      (a, b) => new Date(a.t).getTime() - new Date(b.t).getTime()
    );

    // 按指定间隔分组
    const grouped = Tsrv.utils.groupBy(sortedData, item => {
      // 将时间戳转换成本地时间
      const date = new Date(item.t).toLocaleString();
      const timestamp = new Date(date).getTime();
      return Math.floor(timestamp / interval) * interval;
    });
    // 处理每组数据
    return Object.values(grouped).map(group => {
      const values = group.map(item => item.v);
      // 保留两位小数
      const avg = Math.round(Tsrv.utils.mean(values) * 100) / 100;

      return {
        t: group[0].t,
        v: avg
      };
    });
  }

  private handleDeviceChange(
    chartType: 'voltage' | 'current',
    device: string[] = []
  ) {
    this.chartData[chartType] = this.chartData[chartType].map(item => ({
      ...item,
      active: device.includes(item.key)
    }));
  }
}
</script>

<style lang="scss" scoped>
.rectifier-container {
  height: 100%;
  width: 100%;
  background: #e0e3ea;

  .top-panel {
    width: 100%;
    height: 50%;
    display: flex;
    justify-content: space-between;
    align-content: center;
    margin-bottom: 6px;

    .config-section {
      width: 50%;
      margin-right: 6px;
    }

    .runtime-section {
      width: 50%;
      margin-left: 6px;
      background-color: #fff;
    }
  }

  .chart-section {
    grid-area: chart;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    height: 50%;

    .voltage-chart,
    .current-chart {
      background: #fff;
      display: flex;
      flex-direction: row;
    }

    .left {
      width: 15%;
      padding: 10px;
      margin-top: 65px;
      border: #e0e3ea 1px solid;
      box-sizing: border-box;
    }

    .left time-range-picker,
    .left device-selector {
      display: block;
      margin-bottom: 10px;
    }

    .BaseChart {
      width: 85%;
    }
  }
}
</style>
